package com.lemon.boot.common.interceptor;

import com.lemon.boot.common.annotation.NotAuthorization;
import com.lemon.boot.common.consts.RedisKeyConst;
import com.lemon.boot.common.service.RedisService;
import com.lemon.boot.common.utils.RequestUtil;
import com.lemon.boot.common.utils.ResponseUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.concurrent.TimeUnit;

/**
 * @author 李猛
 * @datetime 2024/8/1 9:22
 * @description Security不需要认证的拦截器
 */
@Slf4j
public class SecurityNotAuthorizationInterceptor implements HandlerInterceptor {
    public RedisService redisService;

    public SecurityNotAuthorizationInterceptor(RedisService redisService) {
        this.redisService = redisService;
    }

    /**
     * 前置拦截
     *
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        log.info("SecurityNotAuthorizationInterceptor.preHandle.uri:{}", request.getRequestURI());
        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;

            //1.获取增强的类上的注解
            NotAuthorization classNotAuthorization = handlerMethod.getBeanType().getAnnotation(NotAuthorization.class);
            if (classNotAuthorization != null) {
                if (classNotAuthorization.enable()) {
                    return verifyCount(request, response, classNotAuthorization);
                } else {
                    return true;
                }
            }

            //2.获取增强方法上的注解
            NotAuthorization methodNotAuthorization = handlerMethod.getMethod().getAnnotation(NotAuthorization.class);
            if (methodNotAuthorization != null) {
                if (methodNotAuthorization.enable()) {
                    return verifyCount(request, response, methodNotAuthorization);
                } else {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 验证次数
     *
     * @param request
     * @param response
     * @param authorization
     * @return
     */
    private boolean verifyCount(HttpServletRequest request, HttpServletResponse response, NotAuthorization authorization) {
        //1.获取参数
        String key = String.format("%s%s:%s", RedisKeyConst.REDIS_KEY_NOT_AUTHORIZATION_METHOD, RequestUtil.getIp(request), request.getRequestURI());
        boolean locked = redisService.lockByTimes(key, authorization.times(), authorization.timeout(), authorization.unit());
        if (!locked) {
            ResponseUtil.fail(response, HttpStatus.FORBIDDEN.value(), getTimeunit(authorization.timeout(), authorization.unit()));
            return false;
        } else {
            return true;
        }
    }

    /**
     * 获取返回的字符串
     *
     * @param timeout
     * @param unit
     * @return
     */
    private static String getTimeunit(int timeout, TimeUnit unit) {
        switch (unit) {
            case MINUTES:
                return String.format("操作频繁，请%s分钟后再试！", timeout);
            case SECONDS:
                return String.format("操作频繁，请%s秒后再试！", timeout);
            case DAYS:
                return String.format("操作频繁，请%s天后再试！", timeout);
            case HOURS:
                return String.format("操作频繁，请%s小时后再试！", timeout);
            default:
                return "操作频繁，请稍后再试！";
        }

    }

    /**
     * 拦截
     *
     * @param request
     * @param response
     * @param handler
     * @param modelAndView
     * @throws Exception
     */
    @Override

    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    /**
     * 请求完成的拦截
     *
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @throws Exception
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}
